package geneticpolyimage;

import java.util.Random;

/**
 * Class GeneticOp provides method for mutation and crossover
 * 
 * @author igor & mattia
 */
public class GeneticOp {

    private double mutationRate;
    private int crossovertype;
    private double crossrate;

    /**
     * Initialize the Genetic Operation Class with
     * specified parameter
     *
     * @param mutrate mutation rate
     * @param crosstype crossover type
     * @param crrate corssover rate
     */
    GeneticOp(double mutrate, int crosstype, double crrate) {
        this.mutationRate = mutrate;
        this.crossovertype = crosstype;
        this.crossrate = crrate;
    }

    public void setCrossRate(double r) {
        crossrate = r;
    }

    public void setMutRate(double r) {
        mutationRate = r;
    }

    /**
     * Generate offspings from two individuals based on
     * crossover rate and crossover type
     *
     * @param father first parent
     * @param mother second parent
     * @return offsprings
     */
    public Individual[] crossover(Individual father, Individual mother) {
        Individual[] sons = new Individual[2];
        if (Math.random() <= crossrate) {
            int how = father.howmanypoly;

            Polygon[] son1polygons = new Polygon[how];
            Polygon[] son2polygons = new Polygon[how];
            if (crossovertype == 0) {
                int p = (int) (Math.random() * how);

                for (int i = 0; i < how; i++) {
                    if (i < p) {
                        son1polygons[i] = (Polygon) father.getPolygons()[i].clone();
                        son2polygons[i] = (Polygon) mother.getPolygons()[i].clone();
                    } else {
                        son2polygons[i] = (Polygon) father.getPolygons()[i].clone();
                        son1polygons[i] = (Polygon) mother.getPolygons()[i].clone();
                    }
                }
            } else {
                Random r = new Random();
                for (int i = 0; i < how; i++) {
                    if (r.nextBoolean()) {
                        son1polygons[i] = (Polygon) father.getPolygons()[i].clone();
                        son2polygons[i] = (Polygon) mother.getPolygons()[i].clone();
                    } else {
                        son2polygons[i] = (Polygon) father.getPolygons()[i].clone();
                        son1polygons[i] = (Polygon) mother.getPolygons()[i].clone();
                    }
                }
            }
            sons[0] = new Individual(son1polygons, father.vertices, father.width, father.height);
            sons[1] = new Individual(son2polygons, father.vertices, father.width, father.height);
        } else {
            sons[0] = (Individual) father.clone();
            sons[1] = (Individual) mother.clone();
        }
        return sons;
    }

    /**
     * Perform mutation of an individual
     * based on mutation rate
     *
     * @param ind individual to mutate
     */
    public void mutate(Individual ind) {
        if (Math.random() <= mutationRate) {
            ind.mutate();
        }
    }
}
